[RecoveryServices.Backup] Add Cross Subscription Backup (CSB) support for Azure VM#29799
[RecoveryServices.Backup] Add Cross Subscription Backup (CSB) support for Azure VM#29799Prabhkiratnitp wants to merge 2 commits into
Conversation
…ervices - Add optional -ContainerSubscriptionId parameter to Enable-AzRecoveryServicesBackupProtection (AzureVMCompute parameter set) to configure backup for a VM in a different subscription than the vault; the CSB path skips discovery/RefreshContainers and constructs the container/protected item URIs and source resource id directly. - Add Original Location Recovery (OLR) support for cross-subscription protected items in Restore-AzRecoveryServicesBackupItem by deriving the container subscription from the recovery point SourceResourceId (no new input required). - Add ContainerSubscriptionId to Get-AzRecoveryServicesBackupItem response (parsed from SourceResourceId) and to the detailed Get-AzRecoveryServicesBackupJob response (from extendedInfo propertyBag). - Add scenario tests and recordings, help examples, and ChangeLog entry. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| Thanks for your contribution! The pull request validation has started. Please revisit this comment for updated status. |
|
Thank you for your contribution @Prabhkiratnitp! We will review the pull request and get back to you soon. |
There was a problem hiding this comment.
Pull request overview
Adds Cross Subscription Backup (CSB) support for Azure VM scenarios in the RecoveryServices.Backup module by enabling protection of VMs that live in a different subscription than the vault, and by improving Original Location Recovery (OLR) behavior for cross-subscription protected items.
Changes:
- Added optional
-ContainerSubscriptionIdtoEnable-AzRecoveryServicesBackupProtection(AzureVM compute parameter set) to enable protection for cross-subscription VMs by bypassing discovery and constructing URIs/sourceResourceId directly. - Updated restore flow for OLR to derive the target subscription from the recovery point’s
SourceResourceId(when-TargetSubscriptionIdis not provided) so staging storage account resolution works for CSB items. - Exposed
ContainerSubscriptionIdonGet-AzRecoveryServicesBackupItem(parsed fromSourceResourceId) and on detailed job responses (Get-AzRecoveryServicesBackupJobDetail) viaextendedInfo.propertyBag["VM Subscription ID"], plus added scenario tests, recordings, help examples, and a changelog entry.
Reviewed changes
Copilot reviewed 15 out of 17 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/RecoveryServices/RecoveryServices.Backup/Cmdlets/Item/EnableAzureRmRecoveryServicesBackupProtection.cs | Adds -ContainerSubscriptionId parameter and forwards it into provider data for enable protection flow. |
| src/RecoveryServices/RecoveryServices.Backup.Providers/Providers/IaasVmPsBackupProvider.cs | Implements CSB enable-protection shortcut path and OLR subscription derivation from recovery point SourceResourceId. |
| src/RecoveryServices/RecoveryServices.Backup.Models/AzureVmModels/AzureVmItem.cs | Adds ContainerSubscriptionId on item model by parsing subscription from SourceResourceId. |
| src/RecoveryServices/RecoveryServices.Backup.Models/AzureVmModels/AzureVmJob.cs | Adds ContainerSubscriptionId field to the detailed Azure VM job model. |
| src/RecoveryServices/RecoveryServices.Backup.Helpers/Conversions/JobConversions.cs | Populates detailed job ContainerSubscriptionId from extendedInfo.propertyBag["VM Subscription ID"] (including CRR variant). |
| src/RecoveryServices/RecoveryServices.Backup.Models/CmdletParamEnums.cs | Extends ItemParams enum with ContainerSubscriptionId for provider data keying. |
| src/RecoveryServices/RecoveryServices.Backup/ParamHelpMsgs.cs | Adds help text constant for the new -ContainerSubscriptionId parameter. |
| src/RecoveryServices/RecoveryServices/help/Enable-AzRecoveryServicesBackupProtection.md | Documents the new parameter and adds a CSB enable-protection example. |
| src/RecoveryServices/RecoveryServices/help/Restore-AzRecoveryServicesBackupItem.md | Adds an example clarifying OLR behavior for cross-subscription protected items. |
| src/RecoveryServices/RecoveryServices/ChangeLog.md | Adds an “Upcoming Release” entry describing CSB support additions across cmdlets. |
| src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/IaasVm/ItemTests.ps1 | Adds CSB protection and CSB OLR restore scenario tests. |
| src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/IaasVm/ItemTests.cs | Wires new CSB item scenario tests into xUnit runner. |
| src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/IaasVm/JobTests.ps1 | Adds CSB job detail scenario test for ContainerSubscriptionId. |
| src/RecoveryServices/RecoveryServices.Backup.Test/ScenarioTests/IaasVm/JobTests.cs | Wires new CSB job scenario test into xUnit runner. |
| src/RecoveryServices/RecoveryServices.Backup.Test/SessionRecords/.../TestAzureVMCSBProtection.json | Recording for CSB protection scenario. |
| src/RecoveryServices/RecoveryServices.Backup.Test/SessionRecords/.../TestAzureVMCSBRestoreOLR.json | Recording for CSB OLR restore scenario. |
| src/RecoveryServices/RecoveryServices.Backup.Test/SessionRecords/.../TestAzureVMCSBJobSubscription.json | Recording for CSB job detail subscription scenario. |
|
@Prabhkiratnitp please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
|
|
|
|
/azp run |
|
Commenter does not have sufficient privileges for PR 29799 in repo Azure/azure-powershell |
|
/azp run |
|
Azure Pipelines successfully started running 3 pipeline(s). |
hiaga
left a comment
There was a problem hiding this comment.
Reviewed the CSB code paths. Build/tests are green and the design is sound; a few items below — only the first (skipping discovery-time validation) is substantive, the rest are minor/nit. Nice work on deriving the container subscription from the recovery point for OLR staging.
| (IaaSVMProtectableItem)protectableObjectResource.Properties; | ||
|
|
||
| if (iaasVmProtectableItem != null) | ||
| if (!string.IsNullOrEmpty(containerSubscriptionId)) |
There was a problem hiding this comment.
question: on the CSB path we skip discovery entirely, so a typo in -Name/-ResourceGroupName or an ineligible VM no longer surfaces the clear "VM not discovered" client error and instead fails opaquely at the backend — is a lightweight existence/eligibility check (or at least a doc note) worth adding?
| [Parameter(Mandatory = false, ParameterSetName = AzureVMComputeParameterSet, | ||
| HelpMessage = ParamHelpMsgs.Item.containerSubscriptionId)] | ||
| [ValidateNotNullOrEmpty] | ||
| public string ContainerSubscriptionId { get; set; } |
There was a problem hiding this comment.
Consider validating -ContainerSubscriptionId as a GUID (ValidatePattern / Guid.TryParse); today a malformed value silently builds a bad sourceResourceId and only fails at the service.
| // and will not find the cross-subscription VM. Hence, we skip discovery and construct the | ||
| // container URI, protected item URI and source resource ID directly. The backend derives the | ||
| // VM's subscription from the source resource ID and configures backup accordingly. | ||
| string vmVersion = isComputeAzureVM ? computeAzureVMVersion : classicComputeAzureVMVersion; |
There was a problem hiding this comment.
-ContainerSubscriptionId is only in AzureVMComputeParameterSet, so isComputeAzureVM is always true here — the classic (iaasvmcontainer / ClassicCompute) branch of these ternaries can never execute; consider dropping it or intentionally supporting classic.
| detailedResponse.Properties.Add(key, vmJob.ExtendedInfo.PropertyBag[key]); | ||
| } | ||
|
|
||
| if (vmJob.ExtendedInfo.PropertyBag.ContainsKey("VM Subscription ID")) |
There was a problem hiding this comment.
nit: extract the "VM Subscription ID" propertyBag key into a named const — it's duplicated here and in GetPSAzureVmJobCrr and will drift.
|
|
||
| containerUri = string.Format("IaasVMContainer;{0};{1};{2}", | ||
| containerType, azureVMRGName, azureVMName); | ||
| protectedItemUri = string.Format("VM;{0};{1};{2}", |
There was a problem hiding this comment.
nit: the rest of the module emits lowercase "vm;" (via GetProtectableItemUri); "VM;" works (ARM is case-insensitive) but is inconsistent.
| Assert-True { $modifiedItem.ContainerSubscriptionId -eq $containerSubscriptionId }; | ||
| } | ||
| finally | ||
| { |
There was a problem hiding this comment.
This finally is empty but the test enables protection — file convention (e.g. Test-AzureRestoreWithCVMOsDiskEncryptionSetId) disables/deletes in finally; please clean up the protected item.
| // Extract the container (VM) subscription from the recovery point's SourceResourceId so that the | ||
| // target storage account is resolved in the correct subscription. No new input is required from | ||
| // the customer. For all other cases, fall back to the vault's (context) subscription. | ||
| if (string.Compare(restoreType, "OriginalLocation") == 0 && !string.IsNullOrEmpty(rp.SourceResourceId)) |
There was a problem hiding this comment.
praise: deriving targetSubscriptionId from rp.SourceResourceId for OLR (so staging storage resolves in the VM's subscription) is the right fix and matches the existing restoreType convention.
Description
Adds Cross Subscription Backup (CSB) support for Azure VM in the RecoveryServices.Backup module:
-ContainerSubscriptionIdparameter to configure backup for a VM residing in a different subscription than the vault. The CSB path skips container discovery/RefreshContainers and constructs the container/protected-item URIs andsourceResourceIddirectly.SourceResourceIdso the staging storage account is resolved in the VM's subscription. No new input required.ContainerSubscriptionId(parsed fromSourceResourceId).ContainerSubscriptionIdto the detailed job response (fromextendedInfoproperty bag).All changes are additive and non-breaking. Added scenario tests with recordings, help examples, and ChangeLog entry.
Mandatory Checklist
Please choose the target release of Azure PowerShell. (⚠️ Target release is a different concept from API readiness. Please click below links for details.)
Check this box to confirm: I have read the Submitting Changes section of
CONTRIBUTING.mdand reviewed the following information:ChangeLog.mdfile(s) appropriatelysrc/{{SERVICE}}/{{SERVICE}}/ChangeLog.md.## Upcoming Releaseheader in the past tense.ChangeLog.mdif no new release is required, such as fixing test case only.